import { CheckUtil } from './check';

/** 数组相关包 **/
export const ArrayUtil = {
  /**
   * 获取树型数据深度
   * @returns {[]}
   * @param list
   */
  getTreeDepth(list) {
    const getNodeDepth = (node) => {
      if (!node.children || node.children.length === 0) {
        return 1;
      }

      let maxDepth = 0;
      node.children.forEach((item) => {
        maxDepth = Math.max(maxDepth, getNodeDepth(item));
      });

      return 1 + maxDepth;
    };

    let maxDepth = 0;
    list.forEach((item) => {
      maxDepth = Math.max(maxDepth, getNodeDepth(item));
    });

    return maxDepth;
  },

  /**
   * 树型数据转换为平铺数据
   * from element-ui/package/table/src/table-header.js
   * @param columns
   * @param childProp
   * @param includeParent
   * @returns {[]}
   */
  getAllColumns(columns, childProp = 'children', includeParent = true) {
    const result = [];
    columns.forEach((column) => {
      if (column[childProp]) {
        if (includeParent) {
          result.push(column);
        }
        result.push.apply(result, this.getAllColumns(column[childProp]));
      } else {
        result.push(column);
      }
    });
    return result;
  },

  /**
   * 树型表头数据转换成行数据，添加跨行跨列属性
   * from element-ui/package/table/src/table-header.js
   * @param originColumns
   * @param childProp
   * @returns {[]}
   */
  convertToRows(originColumns, childProp = 'children') {
    let maxLevel = 1;
    const traverse = (column, parent) => {
      if (parent) {
        column.level = parent.level + 1;
        if (maxLevel < column.level) {
          maxLevel = column.level;
        }
      }
      if (column[childProp]) {
        let colSpan = 0;
        column[childProp].forEach((subColumn) => {
          traverse(subColumn, column);
          colSpan += subColumn.colSpan;
        });
        column.colSpan = colSpan;
      } else {
        column.colSpan = 1;
      }
    };

    originColumns.forEach((column) => {
      column.level = 1;
      traverse(column);
    });

    const rows = [];
    for (let i = 0; i < maxLevel; i++) {
      rows.push([]);
    }

    const allColumns = this.getAllColumns(originColumns, childProp);

    allColumns.forEach((column) => {
      if (!column[childProp]) {
        column.rowSpan = maxLevel - column.level + 1;
      } else {
        column.rowSpan = 1;
      }
      rows[column.level - 1].push(column);
    });

    return rows;
  },

  /**
   * 向树型数组中添加属性，包括 parent 属性，包含父对象数据；
   * @param item
   * @param props key-对象中原有属性，value-增加属性，值为 key 的值
   * @param parent
   */
  setTreeProp(item, props, parent = null) {
    Object.keys(props).forEach((key) => {
      item[props[key]] = item[key];
    });
    item.parent = JSON.parse(JSON.stringify(parent));
    if (CheckUtil.isNotEmptyArray(item.children)) {
      item.children.forEach((o) => this.setTreeProp(o, props, item));
    }
  },

  /**
   * 将一维数组转为树型数组；
   * @param params
   *    list-对象数组,
   *    parentField-子对象中标识父对象属性
   *    parentVal-表明为父对象的值
   *    selfField-自身属性
   *    sortField -排序字段
   */
  getTreeBySimpleList({ list, parentField = 'parentId', parentVal = 0, selfField = 'id', sortField = 'sort' }) {
    const parentList = [];
    const childrenList = [];
    list.forEach((item) => {
      item.parent = null;
      if (item[parentField] === parentVal) {
        parentList.push(item);
      } else {
        childrenList.push(item);
      }
    });

    parentList.sort((a, b) => a[sortField] - b[sortField]);
    childrenList.sort((a, b) => a[sortField] - b[sortField]);

    parentList.forEach((parent) =>
      this.setChildrenProp({
        parent,
        childrenList,
        parentField,
        selfField,
        sortField,
      }),
    );
  },

  /**
   * 给父对象添加子对象，子对象 parent 属性为父对象实例；
   * @param params
   *    parent-父对象
   *    childrenList-待添加子对象
   *    parentField-子对象中标识父对象属性
   *    selfField-自身属性
   *    sortField -排序字段
   */
  setChildrenProp({ parent, childrenList, parentField = 'parentId', selfField = 'id', sortField = 'sort' }) {
    const list = []; // 子菜单列表
    const _list = []; // 除子菜单外其他菜单列表

    childrenList.forEach((child) => {
      if (child[parentField] === parent[selfField]) {
        child.parent = JSON.parse(JSON.stringify(parent));
        list.push(child);
      } else {
        _list.push(child);
      }
    });
    list.sort((a, b) => a[sortField] - b[sortField]);
    parent.children = list;

    if (CheckUtil.isNotEmptyArray(list)) {
      list.forEach((child) => {
        this.setChildrenProp({
          child,
          _list,
          parentField,
          selfField,
          sortField,
        });
      });
    }
  },

  /**
   * 从树型数组中找到某一节点到子孙节点所以属性链，返回该属性值组成的数组，从该节点到最后的子孙节点；
   * @param treeList 对象必须有 children 属性，值为子级数据
   * @param propVal
   * @param prop
   */
  getPropListFormParentByTree(treeList, propVal, prop = 'id') {
    const item = this.getItemByTree(treeList, propVal, prop);
    if (!item) {
      return [];
    }

    const list = [];

    // 递归将 id 推入到 list 中
    const fn = (list, item) => {
      list.push(item[prop]);
      const childList = item.children;
      if (CheckUtil.isNotEmptyArray(childList)) {
        childList.forEach((child) => {
          fn(list, child);
        });
      }
    };
    fn(list, item);

    return list;
  },

  /**
   * 从树型数组中找到某一节点到根节点的属性链，返回该属性值组成的数组，从根节点到该节点；
   * @param treeList 对象必须有 parent 属性，值为父级数据
   * @param propVal
   * @param prop
   * 例如：[1,2]
   */
  getPropListFormChildByTree(treeList, propVal, prop = 'id') {
    let item = this.getItemByTree(treeList, propVal, prop);
    if (!item) {
      return [];
    }
    const list = [item[prop]];
    while (item.parent) {
      item = item.parent;
      list.unshift(item[prop]);
    }

    return list;
  },

  /**
   * 从树型数组中找到某一节点到根节点的属性链，返回该属性值组成的数组，从根节点到该节点；
   * @param treeList 对象必须有 parent 属性，值为父级数据
   * @param propVal
   * @param prop
   * 例如：[{},{}]
   */
  getItemListFormChildByTree(treeList, propVal, prop = 'id') {
    let item = this.getItemByTree(treeList, propVal, prop);
    if (!item) {
      return [];
    }
    const list = [item];
    while (item.parent) {
      item = item.parent;
      list.unshift(item);
    }

    return list;
  },

  /**
   * 从树型数组中找到某一节点对象，返回该节点数据；
   * @param treeList
   * @param propVal
   * @param prop
   */
  getItemByTree(treeList, propVal, prop = 'id') {
    return this.getSimpleListByTree(treeList).find((o) => o[prop] === propVal);
  },

  /**
   * 将树型数组转为一维数组；
   * @param treeList
   * @param childProp 子数组属性名
   */
  getSimpleListByTree(treeList, childProp = 'children') {
    let list = [];
    treeList.forEach((item) => {
      const childList = item[childProp] || [];
      if (CheckUtil.isNotEmptyArray(childList)) {
        list = list.concat(this.getSimpleListByTree(childList, childProp));
      }
      list.push({ ...item, [childProp]: JSON.parse(JSON.stringify(childList)) });
    });
    return list;
  },

  /**
   * 如果数组中不存在 item，将 item 添加到数组中；
   * @param array
   * @param item
   */
  uniqPush(array, item) {
    if (!CheckUtil.isArray(array)) {
      return;
    }

    if (array.findIndex((o) => CheckUtil.isEqual(o, item)) === -1) {
      array.push(item);
    }
  },

  /**
   * 将数组切分成指定长度的数组，可以用来自定义分页；
   * @example sizeSlice([1, 2, 3, 4, 5], 2) => [[1, 2], [3, 4], [5]]
   * @param array
   * @param size
   * @returns {array}
   */
  sizeSlice(array, size) {
    if (!CheckUtil.isArray(array)) {
      return [];
    }

    size = size || 1;
    const len = array.length;
    const res = new Array(Math.ceil(len / size));
    let index = 0;
    let resIndex = 0;

    while (index < len) {
      res[resIndex++] = array.slice(index, (index += size));
    }

    return res;
  },

  /**
   * 根据某一字段及值在对象数组中找到该项并返回另一字段的值；
   * @example findValByKey([{value:1, label:"一"},{value:2, label:"二"}], 1) => "一"
   * @param array
   * @param findVal
   * @param findKey
   * @param returnKey
   * @returns {string|*}
   */
  findValByKey(array, findVal, findKey = 'value', returnKey = 'label') {
    if (!CheckUtil.isObjectArray(array) || CheckUtil.isEmptyString(findVal)) {
      return '';
    }

    return (array.find((item) => CheckUtil.isEqual(item[findKey], findVal)) || {
      [returnKey]: '',
    })[returnKey];
  },

  /**
   * 删除数组的某一项，如果存在的话；
   * @param array
   * @param item
   */
  remove(array, item) {
    if (!CheckUtil.isArray(array)) {
      return;
    }

    const index = array.findIndex((o) => CheckUtil.isEqual(o, item));
    if (index !== -1) {
      array.splice(index, 1);
    }
  },
  // 数组去重
  duplicateRemoval(array, key) {
    return array.filter(
      (obj, index) =>
        array.findIndex(
          (item) => key ? item[key] == obj[key] : item == obj
        ) === index
    );
  }
};
